import { FunctionComponent, useEffect, useState, CSSProperties, useRef } from "react"
import style from "./index.less";
import DogImagePicture from "@/assets/dog.jpg"
import { useSize } from "@/hooks";
import { TimeAccumulate, ITimeAccountExpose } from "../index";
import { EGameLev } from "@/enum";
import { E_GAMELEV_DICT, transformDict } from "@/enum/dict"
import { Modal } from "antd";


/** 游戏参数 */
export interface IGameProps {
    /** 难度 */
    level: EGameLev
    /** 游戏结束回调函数 */
    onFinish?: (useTime: number) => void;
}

/** 游戏配置 */
export interface IGameOptions {
    count: number;
    size: number;
    sequence: Array<{
        /** 块值 */
        value: number;
        /** 块顺序 */
        order: number;
    }>;
}

/** 游戏盒子 */
const GameAwesomeContainer: FunctionComponent<IGameProps> = (props) => {

    const { level, onFinish } = props;
    const gameShell = useRef<HTMLDivElement>(null);
    const { width: gameSize } = useSize(gameShell);
    const [GAME_OPTION, SET_GAME_OPTION] = useState<IGameOptions>({ count: 0, size: 0, sequence: [] });
    const useTime = useRef<number>(0);
    const timeAccumulateRef = useRef<ITimeAccountExpose>(null);
    const isOver = useRef<boolean>(false);
    const [showModal, setShowModal] = useState<boolean>(false);

    useEffect(() => {
        const _count_ = Math.pow(level + 2, 2);
        if (!gameSize) return;
        const list = new Array(_count_ - 1).fill(0).map((_p, q) => q).toSorted((prev, next) => (Math.random() - 0.5));
        SET_GAME_OPTION({
            count: _count_,
            size: gameSize / (level + 2),
            sequence: [...list, _count_ - 1].map((i, index) => ({ value: index, order: i }))
        })
    }, [gameSize, level])

    const imageCssProps = (index: number): CSSProperties => {
        const { size } = GAME_OPTION;
        const offsetX = index % (level + 2), offsetY = Math.floor(index / (level + 2));
        return {
            backgroundImage: `url(${DogImagePicture})`,
            backgroundSize: `${gameSize}px ${gameSize}px`,
            backgroundPosition: `-${offsetX * size}px -${offsetY * size}px`
        }
    }

    /** 判断是否可以点击 */
    const checkIsClick = (index: number): boolean => {
        const { sequence, count } = GAME_OPTION;
        /** 合法方向 */
        const legalDirect: Array<number> = [];
        /** 空索引 */
        const emptyIndex = sequence[count - 1].order;
        const rowcol = level + 2;
        /** 上，下，左，右 */
        const top = emptyIndex - rowcol, down = emptyIndex + rowcol, left = emptyIndex - 1, right = emptyIndex + 1;
        if (top >= 0) legalDirect.push(top);
        if (down <= count - 1) legalDirect.push(down);
        if (left >= 0 && (Math.floor(left / rowcol) == Math.floor(emptyIndex / rowcol))) legalDirect.push(left);
        if (right <= count - 1 && (Math.floor(right / rowcol) == Math.floor(emptyIndex / rowcol))) legalDirect.push(right);
        return legalDirect.includes(index)
    }

    /** 华容道方块切换处理事件 */
    const blockClickHandler = (index: number, e: Event) => {
        e.stopPropagation(); // 防止时间冒泡
        if (isOver.current || !checkIsClick(index)) return;
        let { sequence, count } = GAME_OPTION;
        count--;
        // console.group("click " + index)
        // console.log("manipulate before", JSON.stringify(sequence))
        const a = sequence.find(item => item.order == sequence[index].value)?.value || 0;
        const b = sequence[count].order;
        sequence[count].order = index;
        sequence[a].order = b;
        // console.log("manipulate after", JSON.stringify(sequence))
        // console.groupEnd()
        SET_GAME_OPTION({
            ...GAME_OPTION,
            sequence
        })
        if (isFinish(sequence)) {
            isOver.current = true;
            timeAccumulateRef.current?.stopTime?.()
            onFinish?.(useTime.current)
        }
    }

    /** 判断游戏是否结束 */
    const isFinish = (sequence: IGameOptions["sequence"]) => {
        let result: boolean = true;
        for (let i = 1; i < sequence.length; i++) {
            if (sequence[i].order < sequence[i - 1].order) {
                result = false;
                break;
            }
        }
        return result;
    }

    return (
        <div className={style.game_awesome}>
            <div className={style.game_awesome_user}>
                <span>难度: {transformDict(E_GAMELEV_DICT, level)}</span>
                <span>用时: <TimeAccumulate ref={timeAccumulateRef} format="HH:MM:SS" onTimeChange={t => useTime.current = t} /></span>
            </div>
            <div ref={gameShell} className={style.game_awesome_primary}>
                {
                    GAME_OPTION.sequence.map(({ value, order }) => (
                        value == GAME_OPTION.count - 1 ? null : <div
                            style={{
                                width: GAME_OPTION.size,
                                top: Math.floor(order / (level + 2)) * GAME_OPTION.size,
                                left: (order % (level + 2)) * GAME_OPTION.size,
                                ...(imageCssProps(value))
                            }}
                            className={style.game_awesome_primary_item}
                            key={`block_${value}`}
                            onClick={(e: any) => blockClickHandler(order, e)}
                        ></div>
                    ))
                }
            </div>
            <div className={style.game_awesome_example} onClick={()=>setShowModal(true)}>查看原图</div>
            <Modal title="游戏图例" open={showModal} footer={null} onCancel={()=>setShowModal(false)}>
                <img style={{ width: 300, height: "auto" }} src={DogImagePicture} alt="" />
            </Modal>
        </div>
    )
}

export default GameAwesomeContainer